package com.hiss.basic.system.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.hiss.basic.client.system.ISysDictItemService;
import com.hiss.basic.client.system.ISysDictService;
import com.hiss.basic.model.system.domain.SysDictDomain;
import com.hiss.basic.model.system.request.SysDictCreateRequest;
import com.hiss.basic.model.system.request.SysDictQueryRequest;
import com.hiss.basic.model.system.request.SysDictUpdateRequest;
import com.hiss.basic.model.system.response.SysDictQueryResponse;
import com.hiss.basic.starter.cache.annotation.CacheExpire;
import com.hiss.basic.starter.cache.constant.CacheConstant;
import com.hiss.basic.starter.core.exception.BusinessException;
import com.hiss.basic.starter.core.helper.MapstructHelper;
import com.hiss.basic.starter.core.helper.ValidationHelper;
import com.hiss.basic.starter.mybatis.utils.PageUtils;
import com.hiss.basic.system.mapper.SysDictMapper;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryChain;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.row.Db;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * 系统字典 service impl
 */
@Slf4j
@Service
@CacheConfig(cacheNames = CacheConstant.SYS_DICT_KEY)
public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDictDomain> implements ISysDictService {

    @Resource
    private ISysDictItemService sysDictItemService;

    @Override
    public Page<SysDictQueryResponse> findPageList(SysDictQueryRequest request) {
        QueryWrapper wrapper = new QueryWrapper();
        if (ObjectUtil.isNotNull(request)) {
            wrapper.like(SysDictDomain::getName, request.getName(), StrUtil.isNotBlank(request.getName()));
            wrapper.like(SysDictDomain::getCode, request.getCode(), StrUtil.isNotBlank(request.getCode()));
            wrapper.eq(SysDictDomain::getEnableStatus, request.getEnableStatus(), ObjectUtil.isNotNull(request.getEnableStatus()));
        }
        wrapper.orderBy(SysDictDomain::getCreateTime, false);
        Page page = PageUtils.getPage();
        return pageAs(page, wrapper, SysDictQueryResponse.class);
    }

    @Override
    @CacheExpire(60 * 60 * 3)
    @Cacheable(key = "#code", unless = "#result == null")
    public SysDictDomain findByCode(String code) {
        return QueryChain.of(SysDictDomain.class)
                .eq(SysDictDomain::getCode, code)
                .limit(1)
                .one();
    }

    @Override
    @CacheEvict(allEntries = true)
    public void create(SysDictCreateRequest request) {
        ValidationHelper.validate(request);
        long count = QueryChain.of(SysDictDomain.class)
                .eq(SysDictDomain::getCode, request.getCode())
                .count();
        if (count > 0) {
            throw new BusinessException("字典编码已存在");
        }
        SysDictDomain domain = MapstructHelper.convert(request, SysDictDomain.class);
        save(domain);
    }

    @Override
    @CacheEvict(allEntries = true)
    public void update(SysDictUpdateRequest request) {
        ValidationHelper.validate(request);
        long count = QueryChain.of(SysDictDomain.class)
                .eq(SysDictDomain::getCode, request.getCode())
                .ne(SysDictDomain::getId, request.getId())
                .count();
        if (count > 0) {
            throw new BusinessException("字典编码已存在");
        }
        SysDictDomain domain = MapstructHelper.convert(request, SysDictDomain.class);
        updateById(domain);
    }

    @Override
    @CacheEvict(allEntries = true)
    public void remove(Long id) {
        Db.tx(() -> {
            removeById(id);

            sysDictItemService.removeByDictId(id);
            return Boolean.TRUE;
        });
    }
}
